{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## NumPy - 简介\n",
    "NumPy 是一个 Python 包。 它代表 “Numeric Python”。 它是一个由多维数组对象和用于处理数组的例程集合组成的库。Numeric，即 NumPy 的前身，是由 Jim Hugunin 开发的。 也开发了另一个包 Numarray ，它拥有一些额外的功能。 2005年，Travis Oliphant 通过将 Numarray 的功能集成到 Numeric 包中来创建 NumPy 包。 这个开源项目有很多贡献者。\n",
    "\n",
    "### NumPy 操作\n",
    "使用NumPy，开发人员可以执行以下操作：\n",
    "1. 数组的算数和逻辑运算。\n",
    "2. 傅立叶变换和用于图形操作的例程。\n",
    "3. 与线性代数有关的操作。 NumPy 拥有线性代数和随机数生成的内置函数。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### ndarray\n",
    "NumPy 中定义的最重要的对象是称为 ndarray 的 N 维数组类型。 它描述相同类型的元素集合。 可以使用基于零的索引访问集合中的项目。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义矩阵变量并输出变量的一些属性\n",
    "# 用np.array()生成矩阵\n",
    "arr=np.array([[1,2,3],\n",
    "              [4,5,6]])\n",
    "print(arr)\n",
    "print('维度: ',arr.ndim)\n",
    "print('形状: ',arr.shape)\n",
    "print('大小: ', arr.size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义一些特殊矩阵\n",
    "# 指定矩阵数据类型\n",
    "arr=np.array([[1,2,3],\n",
    "              [4,5,6]],\n",
    "              dtype=np.float64) \n",
    "print(arr.dtype)\n",
    "\n",
    "# 用np.zeros()生成全零矩阵\n",
    "arr_zeros=np.zeros( (2,3) )\n",
    "print(arr_zeros)\n",
    "\n",
    "# 用np.ones()生成全一矩阵\n",
    "arr_ones=np.ones( (2,3) )\n",
    "print(arr_ones)\n",
    "\n",
    "# 用np.arange()生成数列\n",
    "arr=np.arange(6,12)\n",
    "print(arr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### NumPy - 数据类型\n",
    "\n",
    "序号\t数据类型及描述\n",
    "1.\tbool_存储为一个字节的布尔值(真或假)\n",
    "2.\tint_默认整数，相当于 C 的long，通常为int32或int64\n",
    "3.\tintc相当于 C 的int，通常为int32或int64\n",
    "4.\tintp用于索引的整数，相当于 C 的size_t，通常为int32或int64\n",
    "5.\tint8 8字节(-128 ~ 127)\n",
    "6.\tint16 16 位整数(-32768 ~ 32767)\n",
    "7.\tint32 32 位整数(-2147483648 ~ 2147483647)\n",
    "8.\tint64 64 位整数(-9223372036854775808 ~ 9223372036854775807)\n",
    "9.\tuint8 8 位无符号整数(0 ~ 255)\n",
    "10.\tuint16 16 位无符号整数(0 ~ 65535)\n",
    "11.\tuint32 32 位无符号整数(0 ~ 4294967295)\n",
    "12.\tuint64 64 位无符号整数(0 ~ 18446744073709551615)\n",
    "13.\tfloat_float64的简写\n",
    "14.\tfloat16半精度浮点：符号位，5 位指数，10 位尾数\n",
    "15.\tfloat32单精度浮点：符号位，8 位指数，23 位尾数\n",
    "16.\tfloat64双精度浮点：符号位，11 位指数，52 位尾数\n",
    "17.\tcomplex_complex128的简写\n",
    "18.\tcomplex64复数，由两个 32 位浮点表示(实部和虚部)\n",
    "19.\tcomplex128复数，由两个 64 位浮点表示(实部和虚部)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#int8，int16，int32，int64 可替换为等价的字符串 'i1'，'i2'，'i4'，以及其他。 \n",
    "\n",
    "dt = np.dtype('i4')\n",
    "print(dt)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### NumPy - 切片和索引\n",
    "ndarray对象的内容可以通过索引或切片来访问和修改，就像 Python 的内置容器对象一样。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.array([[1,2,3],[3,4,5],[4,5,6]])  \n",
    "print(a)\n",
    "# 对始于索引的元素进行切片  \n",
    "print('现在我们从索引 a[1:] 开始对数组切片')\n",
    "print(a[1:])\n",
    "\n",
    "# 现在我们从第二行切片所有元素：  \n",
    "print ('第二行的元素是：')\n",
    "print (a[1,...])  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### NumPy - 广播\n",
    "术语广播是指 NumPy 在算术运算期间处理不同形状的数组的能力。 对数组的算术运算通常在相应的元素上进行。 如果两个阵列具有完全相同的形状，则这些操作被无缝执行。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.array([1,2,3,4]) \n",
    "b = np.array([10,20,30,40]) \n",
    "c = a * b \n",
    "print(c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果两个数组的维数不相同，则元素到元素的操作是不可能的。 然而，在 NumPy 中仍然可以对形状不相似的数组进行操作，因为它拥有广播功能。 较小的数组会广播到较大数组的大小，以便使它们的形状可兼容。\n",
    "\n",
    "如果满足以下规则，可以进行广播：\n",
    "1. ndim较小的数组会在前面追加一个长度为 1 的维度。\n",
    "2. 输出数组的每个维度的大小是输入数组该维度大小的最大值。\n",
    "3. 如果输入在每个维度中的大小与输出大小匹配，或其值正好为 1，则在计算中可它。\n",
    "4. 如果输入的某个维度大小为 1，则该维度中的第一个数据元素将用于该维度的所有计算。\n",
    "\n",
    "如果上述规则产生有效结果，并且满足以下条件之一，那么数组被称为可广播的。\n",
    "1. 数组拥有相同形状。\n",
    "2. 数组拥有相同的维数，每个维度拥有相同长度，或者长度为 1。\n",
    "3. 数组拥有极少的维度，可以在其前面追加长度为 1 的维度，使上述条件成立。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.array([[0.0,0.0,0.0],[10.0,10.0,10.0],[20.0,20.0,20.0],[30.0,30.0,30.0]]) \n",
    "b = np.array([[1.0],[2],[3],[4]])  \n",
    "#b = np.array([1.0])\n",
    "#b = np.array([1.0,2,3])\n",
    "print('第一个数组：'  )\n",
    "print(a) \n",
    "print('\\n'  )\n",
    "print('第二个数组：'  )\n",
    "print(b) \n",
    "print('\\n')  \n",
    "print('第一个数组加第二个数组：')\n",
    "print(a + b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 练习\n",
    "#将列表变成Numpy数组  \n",
    "data=[2,3,4,5]  \n",
    "arr = np.array(data)\n",
    "print(arr)  \n",
    "  \n",
    "#创建二维矩阵  \n",
    "data=[[1,2,3],[7,8,9]]  \n",
    "arr = np.array(data)\n",
    "print(arr)  \n",
    "  \n",
    "#输出arr的数据类型  \n",
    "data=[2,3,4,5]  \n",
    "arr = np.array(data)\n",
    "print(arr.dtype)  \n",
    "\n",
    "#输出2*2的矩阵，指定数据类型int32  \n",
    "arr=np.array([2,2],dtype=\"int32\")  \n",
    "print(arr)  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### NumPy - 数组操作\n",
    "\n",
    "序号\t形状及描述\n",
    "1.\treshape 不改变数据的条件下修改形状\n",
    "2.\tflat 数组上的一维迭代器\n",
    "3.\tflatten 返回折叠为一维的数组副本\n",
    "4.\travel 返回连续的展开数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.arange(8)\n",
    "print('原始数组：'  )\n",
    "print(a) \n",
    "print('\\n'  )\n",
    "b = a.reshape(4,2)\n",
    "print('修改后的数组：'  )\n",
    "print(b) \n",
    "print('\\n'  )\n",
    "print('展开的数组：')\n",
    "print (b.flatten())\n",
    "print('以 F 风格顺序展开的数组：')\n",
    "print (b.flatten(order = 'F'))\n",
    "# order：'C' — 按行，'F' — 按列，'A' — 原顺序，'k' — 元素在内存中的出现顺序。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('原始数组：'  )\n",
    "print(b) \n",
    "print('\\n'  )\n",
    "print('转置数组：'  )\n",
    "print(np.transpose(b)) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### broadcast_to\n",
    "此函数将数组广播到新形状。 它在原始数组上返回只读视图。 它通常不连续。 如果新形状不符合 NumPy 的广播规则，该函数可能会抛出ValueError"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.arange(4).reshape(1,4)\n",
    "print('原始数组：'  )\n",
    "print(a) \n",
    "print('\\n'  )\n",
    "print('调用 broadcast_to 函数之后：')\n",
    "print(np.broadcast_to(a,(4,4)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### numpy.concatenate\n",
    "\n",
    "数组的连接是指连接。 此函数用于沿指定轴连接相同形状的两个或多个数组。 该函数接受以下参数。\n",
    "\n",
    "```numpy.concatenate((a1, a2, ...), axis)```\n",
    "\n",
    "1. Python其中：a1, a2, ...：\n",
    "2. 相同类型的数组序列axis：沿着它连接数组的轴，默认为 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.array([[1,2],[3,4]])\n",
    "\n",
    "print('原始数组：'  )\n",
    "print(a) \n",
    "print('\\n'  )\n",
    "b = np.array([[5,6],[7,8]])\n",
    "\n",
    "print('第二个数组：'  )\n",
    "print(b) \n",
    "print('\\n'  ) \n",
    "# 两个数组的维度相同\n",
    "\n",
    "print( '沿轴 0 连接两个数组：')\n",
    "print (np.concatenate((a,b)))\n",
    "print ('\\n'  )\n",
    "\n",
    "print ('沿轴 1 连接两个数组：')\n",
    "print (np.concatenate((a,b),axis = 1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 添加/删除元素\n",
    "序号\t元素及描述\n",
    "1.\tresize 返回指定形状的新数组\n",
    "2.\tappend 将值添加到数组末尾\n",
    "3.\tinsert 沿指定轴将值插入到指定下标之前\n",
    "4.\tdelete 返回删掉某个轴的子数组的新数组\n",
    "5.\tunique 寻找数组内的唯一元素"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.array([[1,2,3],[4,5,6]])\n",
    "\n",
    "print ('第一个数组：')\n",
    "print (a)\n",
    "print ('\\n')\n",
    "\n",
    "print ('第一个数组的形状：')\n",
    "print (a.shape)\n",
    "print ('\\n')  \n",
    "b = np.resize(a, (3,2))\n",
    "\n",
    "print ('第二个数组：')\n",
    "print (b)\n",
    "print ('\\n'  )\n",
    "\n",
    "print ('第二个数组的形状：')\n",
    "print (b.shape)\n",
    "print ('\\n'  )\n",
    "# 要注意 a 的第一行在 b 中重复出现，因为尺寸变大了\n",
    "\n",
    "print ('修改第二个数组的大小：')\n",
    "b = (np.resize(a,(3,3)))\n",
    "print (b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "a = np.array([[1,2,3],[4,5,6]])\n",
    "\n",
    "print('第一个数组：')\n",
    "print(a)\n",
    "print('\\n')  \n",
    "\n",
    "print('向数组添加元素：')\n",
    "print(np.append(a, [7,8,9]))\n",
    "print('\\n')  \n",
    "\n",
    "print('沿轴 0 添加元素：')\n",
    "print(np.append(a, [[7,8,9]],axis = 0))\n",
    "print('\\n')  \n",
    "\n",
    "print('沿轴 1 添加元素：')\n",
    "print(np.append(a, [[5,5,5],[7,8,9]],axis = 1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.array([[1,2],[3,4],[5,6]])\n",
    "\n",
    "print('第一个数组：')\n",
    "print(a)\n",
    "print('\\n'  )\n",
    "\n",
    "print('未传递 Axis 参数。 在插入之前输入数组会被展开。')\n",
    "print(np.insert(a,3,[11,12]))\n",
    "print('\\n'  )\n",
    "print('传递了 Axis 参数。 会广播值数组来配输入数组。')\n",
    "\n",
    "print('沿轴 0 广播：')\n",
    "print(np.insert(a,1,[11],axis = 0))\n",
    "print('\\n'  )\n",
    "\n",
    "print('沿轴 1 广播：')\n",
    "print(np.insert(a,1,11,axis = 1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.arange(12).reshape(3,4)\n",
    "print('第一个数组：')\n",
    "print(a)\n",
    "print('\\n'  )\n",
    "\n",
    "print('未传递 Axis 参数。 在插入之前输入数组会被展开。')\n",
    "print(np.delete(a,5))\n",
    "print('\\n'  )\n",
    "\n",
    "print('删除第二列：'  )\n",
    "print(np.delete(a,1,axis = 0))\n",
    "print('\\n'  )\n",
    "\n",
    "print('包含从数组中删除的替代值的切片：')\n",
    "a = np.array([1,2,3,4,5,6,7,8,9,10])\n",
    "print(np.delete(a, np.s_[::3]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#输出第1行  \n",
    "arr=np.arange(1,10).reshape(3,3)\n",
    "print(arr)\n",
    "print(\"===================\")\n",
    "print(arr[0])  \n",
    "print(\"===================\")\n",
    "# #输出2，3行  \n",
    "print(arr[1:])  \n",
    "print(\"===================\")\n",
    "#输出第一行第一个  \n",
    "print(arr[1,1])\n",
    "print(\"===================\")\n",
    "#输出所有行和2，3列  \n",
    "print(arr[:,1:])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### NumPy - 运算函数\n",
    "\n",
    "很容易理解的是，NumPy 包含大量的各种数学运算功能。 NumPy 提供标准的三角函数，算术运算的函数，复数处理函数等。\n",
    "\n",
    "#### 三角函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.array([0,30,45,60,90])  \n",
    "print( '含有正弦值的数组：')\n",
    "sin = np.sin(a*np.pi/180)  \n",
    "print(sin)\n",
    "print( '\\n'  )\n",
    "print( '计算角度的反正弦，返回值以弧度为单位：')\n",
    "inv = np.arcsin(sin)  \n",
    "print(inv)\n",
    "print( '\\n'  )\n",
    "print( '通过转化为角度制来检查结果：'  )\n",
    "print(np.degrees(inv)  )\n",
    "print( '\\n'  )\n",
    "print( 'arccos 和 arctan 函数行为类似：')\n",
    "cos = np.cos(a*np.pi/180)  \n",
    "print(cos)\n",
    "print( '\\n'  )\n",
    "print( '反余弦：')\n",
    "inv = np.arccos(cos)  \n",
    "print(inv)\n",
    "print( '\\n'  )\n",
    "print( '角度制单位：'  )\n",
    "print(np.degrees(inv)  )\n",
    "print( '\\n'  )\n",
    "print( 'tan 函数：')\n",
    "tan = np.tan(a*np.pi/180)  \n",
    "print(tan)\n",
    "print( '\\n'  )\n",
    "print( '反正切：')\n",
    "inv = np.arctan(tan)  \n",
    "print(inv)\n",
    "print( '\\n'  )\n",
    "print( '角度制单位：'  )\n",
    "print(np.degrees(inv))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 舍入函数\n",
    "\n",
    "这个函数返回四舍五入到所需精度的值。 该函数接受以下参数。\n",
    "\n",
    "```numpy.around(a,decimals)```\n",
    "\n",
    "其中：\n",
    "序号\t参数及描述\n",
    "1.\ta 输入数组\n",
    "2.\tdecimals 要舍入的小数位数。 默认值为0。 如果为负，整数将四舍五入到小数点左侧的位置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.array([1.0,5.55,  123,  0.567,  25.532])  \n",
    "print( '原数组：'  )\n",
    "print(a)\n",
    "print( '\\n'  )\n",
    "print( '舍入后：'  )\n",
    "print(np.around(a)  )\n",
    "print(np.around(a, decimals =  2)  )\n",
    "print(np.around(a, decimals =  -1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 算数运算\n",
    "用于执行算术运算(如add()，subtract()，multiply()和divide())的输入数组必须具有相同的形状或符合数组广播规则。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.arange(9, dtype = np.float_).reshape(3,3)  \n",
    "print( '第一个数组：'  )\n",
    "print(a )\n",
    "print( '\\n'  )\n",
    "print( '第二个数组：' )\n",
    "b = np.array([10,10,10])  \n",
    "print(b )\n",
    "print( '\\n'  )\n",
    "print( '两个数组相加：'  )\n",
    "print(np.add(a,b)  )\n",
    "print( '\\n'  )\n",
    "print( '两个数组相减：'  )\n",
    "print(np.subtract(a,b)  )\n",
    "print( '\\n'  )\n",
    "print( '两个数组相乘：'  )\n",
    "print(np.multiply(a,b)  )\n",
    "print( '\\n'  )\n",
    "print( '两个数组相除：'  )\n",
    "print(np.divide(a,b))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "a = np.array([10,100,1000])  \n",
    "print( '我们的数组是；'  )\n",
    "print(a )\n",
    "print( '\\n'  )\n",
    "print( '调用 power 函数：'  )\n",
    "print(np.power(a,2)  )\n",
    "print( '\\n'  )\n",
    "print( '第二个数组：' )\n",
    "b = np.array([1,2,3])  \n",
    "print(b )\n",
    "print( '\\n'  )\n",
    "print( '再次调用 power 函数：'  )\n",
    "print(np.power(a,b))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#练习\n",
    "#使用两种方法对其求三次方\n",
    "a = np.arange(100, dtype = np.float_).reshape(2,3,2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 统计函数\n",
    "NumPy 有很多有用的统计函数，用于从数组中给定的元素中查找最小，最大，百分标准差和方差等。 函数说明如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.array([[3,7,5],[8,4,3],[2,4,9]])  \n",
    "print( '我们的数组是：'  )\n",
    "print(a )\n",
    "print( '\\n'  )\n",
    "print( '调用 amin() 函数：'  )\n",
    "print(np.amin(a,1)  )\n",
    "print( '\\n'  )\n",
    "print( '再次调用 amin() 函数：'  )\n",
    "print(np.amin(a,0)  )\n",
    "print( '\\n'  )\n",
    "print( '调用 amax() 函数：'  )\n",
    "print(np.amax(a)  )\n",
    "print( '\\n'  )\n",
    "print( '再次调用 amax() 函数：'  )\n",
    "print(np.amax(a, axis =  0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 百分位数是统计中使用的度量，表示小于这个值得观察值占某个百分比。\n",
    "a = np.array([[30,40,70],[80,20,10],[50,90,60]])  \n",
    "print( '我们的数组是：'  )\n",
    "print(a )\n",
    "print( '\\n'  )\n",
    "print( '调用 percentile() 函数：'  )\n",
    "print(np.percentile(a,50)  )\n",
    "print( '\\n'  )\n",
    "print( '沿轴 1 调用 percentile() 函数：'  )\n",
    "print(np.percentile(a,50, axis =  1)  )\n",
    "print( '\\n'  )\n",
    "print( '沿轴 0 调用 percentile() 函数：'  )\n",
    "print(np.percentile(a,50, axis =  0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#中值定义为将数据样本的上半部分与下半部分分开的值。\n",
    "a = np.array([[30,65,70],[80,95,10],[50,90,60]])  \n",
    "print( '我们的数组是：'  )\n",
    "print(a )\n",
    "print( '\\n'  )\n",
    "print( '调用 median() 函数：'  )\n",
    "print(np.median(a)  )\n",
    "print( '\\n'  )\n",
    "print( '沿轴 0 调用 median() 函数：'  )\n",
    "print(np.median(a, axis =  0)  )\n",
    "print( '\\n'  )\n",
    "print( '沿轴 1 调用 median() 函数：'  )\n",
    "print(np.median(a, axis =  1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 算术平均值是沿轴的元素的总和除以元素的数量。\n",
    "a = np.array([[1,2,3],[3,4,5],[4,5,6]])  \n",
    "print( '我们的数组是：'  )\n",
    "print(a )\n",
    "print( '\\n'  )\n",
    "print( '调用 mean() 函数：'  )\n",
    "print(np.mean(a)  )\n",
    "print( '\\n'  )\n",
    "print( '沿轴 0 调用 mean() 函数：'  )\n",
    "print(np.mean(a, axis =  0)  )\n",
    "print( '\\n'  )\n",
    "print( '沿轴 1 调用 mean() 函数：'  )\n",
    "print(np.mean(a, axis =  1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 标准差\n",
    "标准差是与均值的偏差的平方的平均值的平方根。 标准差公式如下：\n",
    "\n",
    "``` std = sqrt(mean((x - x.mean())**2)) ```\n",
    "\n",
    "如果数组是[1，2，3，4]，则其平均值为2.5。 因此，差的平方是[2.25,0.25,0.25,2.25]，并且其平均值的平方根除以4，即sqrt(5/4)是1.1180339887498949"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(np.std([1,2,3,4]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 方差\n",
    "方差是偏差的平方的平均值，即\n",
    "```mean((x - x.mean())** 2)```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(np.var([1,2,3,4]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 线性代数模块"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 求范数\n",
    "a=np.array([5,12])\n",
    "print(a)\n",
    "b=np.linalg.norm(a) # norm表示范数，默认求2范数，ord=1求1范数，ord=np.inf求无穷范数\n",
    "print(b)\n",
    "\n",
    "# 求矩阵的迹、行列式、秩、特征值、特征向量\n",
    "b = np.array([\n",
    "    [1, 2, 3],\n",
    "    [4, 5, 6],\n",
    "    [7, 8, 9]\n",
    "])\n",
    "\n",
    "print(np.trace(b))      # 15，求矩阵的迹（主对角线上各个元素的总和）\n",
    "\n",
    "c=np.linalg.det(b)\n",
    "print(c)                # 输出一个很小的值6.66133814775e-16，求矩阵的行列式值\n",
    "                        # 如果希望输出为0，使用round(c, 2)，四舍五入保留小数点后两位\n",
    "                        # 不过对精度要求高可以使用decimal模块\n",
    "\n",
    "c=np.linalg.matrix_rank(b)\n",
    "print(c)                # 2，求矩阵的秩\n",
    "\n",
    "u,v=np.linalg.eig(b) # u为特征值\n",
    "print(u)\n",
    "print(v)\n",
    "\n",
    "# 矩阵分解\n",
    "# Cholesky分解并重建\n",
    "d = np.array([\n",
    "    [2, 1],\n",
    "    [1, 2]\n",
    "])\n",
    "\n",
    "l = np.linalg.cholesky(d)\n",
    "print(l) # 得到下三角矩阵\n",
    "e=np.dot(l, l.T)\n",
    "print(e) # 重建得到矩阵d\n",
    "\n",
    "\n",
    "# 对不正定矩阵，进行SVD分解并重建\n",
    "U, s, V = np.linalg.svd(d)\n",
    "\n",
    "S = np.array([\n",
    "    [s[0], 0],\n",
    "    [0, s[1]]\n",
    "])\n",
    "\n",
    "print(np.dot(U, np.dot(S, V))) # 重建得到矩阵d\n",
    "\n",
    "# 矩阵乘法\n",
    "# https://docs.scipy.org/doc/numpy/reference/generated/numpy.dot.html#numpy.dot\n",
    "print(np.dot(3, 4)) # 12，0-D矩阵相乘（也就是标量相乘）\n",
    "\n",
    "print(np.dot([2j, 3j], [2j, 3j])) # (-13+0j)，1-D矩阵相乘（实际上是向量做点积）\n",
    "\n",
    "a=[[1, 0], [0, 1]]\n",
    "b=[[4, 1, 0], [2, 2, 0]]\n",
    "print(np.dot(a, b))\n",
    "'''\n",
    "array([[4, 1],\n",
    "    [2, 2]])\n",
    "2-D矩阵相乘\n",
    "这里是2*2矩阵和2*3矩阵相乘，结果为2*3矩阵\n",
    "'''\n",
    "\n",
    "a=[[1, 0], [1, 2]]\n",
    "b=[2,2]\n",
    "c=np.dot(a,b)\n",
    "print(c) \n",
    "'''\n",
    "[2 6]\n",
    "注意这里b是向量\n",
    "numpy处理时并不是按照矩阵乘法规则计算\n",
    "而是向量点积\n",
    "也就是np.dot([1, 0],[1, 2])和np.dot([1, 2],[2,2])\n",
    "'''\n",
    "\n",
    "# 再做个实验来区别向量乘法和矩阵乘法\n",
    "b=np.array([\n",
    "    [1, 2, 3],\n",
    "    [4, 5, 6],\n",
    "    [7, 8, 9]\n",
    "])\n",
    "\n",
    "# 这里插播一下，np.array([1,0,1])是3维向量，而不是1*3的矩阵\n",
    "c1=np.array([[1,0,2]]) \n",
    "print(c1.shape) # (1, 3)，这是一个1*3的矩阵\n",
    "c2=np.array([1,0,2])\n",
    "print(c2.shape) # (3,)，这是一个3维向量\n",
    "\n",
    "# print(np.dot(b,c1)) # 报错，不符合矩阵乘法规则\n",
    "print(np.dot(b,c2)) # [ 7 16 25]，点积运算\n",
    "\n",
    "print(np.dot(c1,b)) # [[15 18 21]]，矩阵乘法运算规则\n",
    "print(np.dot(c2,b)) # [15 18 21]，点积运算\n",
    "\n",
    "# 还要补充一下，如果是用python自带的*运算符计算则是广播机制\n",
    "print(b*c1) # print(b*c2)结果一样\n",
    "\n",
    "print(b+c1) # print(b*c2)结果一样\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
